package metamodel;

import java.util.List;
import java.util.Iterator;

/**
 * Represents a polymorphous class
 * Date: 17.06.2005
 */
public class PolyClassNode extends ClassNode {

    // the concrete subclasses
    List<ClassNode> subClazzes;

    /** Creates a new PolyClassNode*/
    public PolyClassNode(String typeName, List<ClassNode> subClasses) {
        super(typeName);
        this.subClazzes = subClasses;
        for (Iterator iterator = subClasses.iterator(); iterator.hasNext();) {
            ClassNode classNode = (ClassNode) iterator.next();
            classNode.setDeclaringParent(this);
        }
    }

    public Object createInstance(Object value) {
        ClassNode actualClass=getClazzForConcreteTypeName(value.getClass().getName());
        return actualClass.createInstance(value);
    }


    public String toString() {
        return "PolyClass "+getTypeName();
    }

    public List<ClassNode> getSubClazzes() {
        return subClazzes;
    }

    public void setSubClazzes(List subClazzes) {
        throw new RuntimeException("Don't!");
        //this.subClazzes = subClazzes;
    }

    public ClassNode getClazzForConcreteTypeName(String name){
        for (Iterator iterator = subClazzes.iterator(); iterator.hasNext();) {
            ClassNode classNode = (ClassNode) iterator.next();
            if (classNode ==null){
                System.out.println("Attention poly type "+getTypeName()+" has subClass null");
            }

                Class type = classNode.getType();
                Class cls = resolveClass(name);
                if (type.isAssignableFrom(cls))
                {
                    return classNode;
               }
        }
        throw new RuntimeException("Type "+name+" could not be resolved.");
    }

    public boolean isPoly() {
        return true;
    }

    public void setDeclaringParent(ClassNode declaringParent) {
        super.setDeclaringParent(declaringParent);
        for (Iterator iterator = subClazzes.iterator(); iterator.hasNext();) {
            ClassNode classNode = (ClassNode) iterator.next();
            classNode.setDeclaringParent(this);
        }
    }

    public PolyClassNode getPoly() {
        return this;
    }
}
